package com.fsquare.admin.service.handler;

import java.util.List;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;

import org.broadleafcommerce.common.exception.ServiceException;
import org.broadleafcommerce.core.catalog.domain.Product;
import org.broadleafcommerce.core.catalog.domain.Sku;
import org.broadleafcommerce.core.catalog.service.CatalogService;
import org.broadleafcommerce.openadmin.dto.CriteriaTransferObject;
import org.broadleafcommerce.openadmin.dto.DynamicResultSet;
import org.broadleafcommerce.openadmin.dto.PersistencePackage;
import org.broadleafcommerce.openadmin.server.dao.DynamicEntityDao;
import org.broadleafcommerce.openadmin.server.service.handler.CustomPersistenceHandlerAdapter;
import org.broadleafcommerce.openadmin.server.service.persistence.module.PersistenceModule;
import org.broadleafcommerce.openadmin.server.service.persistence.module.RecordHelper;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.FieldPathBuilder;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.FilterMapping;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.Restriction;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.predicate.PredicateProvider;
import org.springframework.stereotype.Component;

import com.fsquare.inventory.service.InventoryService;

@Component("fsquareSkuMovementCustomPersistenceHandler")
public class SkuMovementCustomPersistenceHandler extends CustomPersistenceHandlerAdapter {

//	private static final Log LOG = LogFactory.getLog(GenreCustomPersistenceHandler.class);

//    public static final String MOVIE_GENRES = "movieGenres";
    public static final String REQUESTING_ENTITY_ID = "product";

	@Resource(name = "fsquareInventoryService")
	protected InventoryService inventoryService;
	
	@Resource(name = "blCatalogService")
	protected CatalogService catalogService;

    @Override
    public Boolean canHandleFetch(PersistencePackage persistencePackage) {
        String ceilingEntityFullyQualifiedClassname = persistencePackage.getCeilingEntityFullyQualifiedClassname();
        try {
            Class testClass = Class.forName(ceilingEntityFullyQualifiedClassname);
            return Sku.class.isAssignableFrom(testClass);
        } catch (ClassNotFoundException e) {
            return false;
        }
    }


    @Override
    public DynamicResultSet fetch(PersistencePackage persistencePackage, CriteriaTransferObject cto, DynamicEntityDao dynamicEntityDao, RecordHelper helper) throws ServiceException {

        Long productId = null;
        boolean movieFilteredGenres = false;
        for (String criteria : persistencePackage.getCustomCriteria()) {
            if (criteria.startsWith(REQUESTING_ENTITY_ID)) {
            	productId = Long.parseLong(criteria.split("=")[1]);
            } 
//            else if (MOVIE_GENRES.equals(criteria)){
//                movieFilteredGenres = true;
//            }
        }
//
        if (productId != null) {
            FilterMapping genreFilter = getFilterMapping(productId, cto, dynamicEntityDao);
            if (genreFilter != null) {
                cto.getAdditionalFilterMappings().add(genreFilter);
            }
        }

        PersistenceModule myModule = helper.getCompatibleModule(persistencePackage.getPersistencePerspective().getOperationTypes().getFetchType());
        return myModule.fetch(persistencePackage, cto);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    protected FilterMapping getFilterMapping(Long productId, CriteriaTransferObject cto, DynamicEntityDao dynamicEntityDao) {

    	Product product = catalogService.findProductById(productId);
    	
        if (product != null) {
        	final Sku sku = product.getDefaultSku();
            return new FilterMapping().withRestriction(new Restriction().withPredicateProvider(new PredicateProvider() {

					@Override
					public Predicate buildPredicate(CriteriaBuilder builder, FieldPathBuilder fieldPathBuilder, From root, String ceilingEntity,
							String fullPropertyName, Path explicitPath, List directValues) {
						
						Predicate predicate = builder.equal(root.get("sku").as(Sku.class), sku);

                        return predicate;
					}
                    
                })
            );
        }
        return null;
    }
}
